package com.czn.shopdemo.service.impl;

import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czn.shopdemo.config.MinioConfig;
import com.czn.shopdemo.mapper.BusinessMapper;
import com.czn.shopdemo.mapper.CategoryMapper;
import com.czn.shopdemo.mapper.GoodsMapper;
import com.czn.shopdemo.model.Business;
import com.czn.shopdemo.model.Category;
import com.czn.shopdemo.model.Goods;
import com.czn.shopdemo.model.enums.ResultCodeEnum;
import com.czn.shopdemo.model.exception.CustomException;
import com.czn.shopdemo.model.vo.GoodsVO;
import com.czn.shopdemo.service.BusinessService;
import com.czn.shopdemo.service.GoodsService;
import com.czn.shopdemo.utils.MinioUtil;
import com.czn.shopdemo.utils.TokenInfoUtil;
import com.czn.shopdemo.utils.Utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.UUID;

/**
 * @author Zenan Chen
 * @date 2023/4/3 11:04
 */
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements GoodsService {

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private BusinessServiceImpl businessService;

    @Autowired
    private MinioConfig minioConfig;

    /**
     * 查询商品列表，分页和模糊查询
     *
     * @param pageNo
     * @param pageSize
     * @param goodsVO
     * @return
     */
    @Override
    public Page<Goods> getGoodsList(Integer pageNo, Integer pageSize, GoodsVO goodsVO) {
        Page<Goods> page = new Page<>(pageNo, pageSize);
        LambdaQueryWrapper<Goods> queryWrapper = Wrappers.lambdaQuery(Goods.class).eq(Goods::getIsDeleted, "0").eq(Goods::getOnLine, "1");
        if (!Utils.isEmptyStr(goodsVO.getCode())) {
            queryWrapper.eq(Goods::getCode, goodsVO.getCode());
        }
        if (!Utils.isEmptyStr(goodsVO.getName())) {
            queryWrapper.like(Goods::getName, goodsVO.getName());
        }
        Page<Goods> goodsPage = goodsMapper.selectPage(page, queryWrapper);
        goodsPage.getRecords().stream().forEach(goods -> fillGoods(goods));
        return goodsPage;
    }

    /**
     * 给商品填充标签信息
     *
     * @param goods
     */
    private void fillGoods(Goods goods) {
        LambdaQueryWrapper<Category> categoryWrapper = Wrappers.lambdaQuery(Category.class).eq(Category::getUuid, goods.getCategoryId());
        Category category = categoryMapper.selectOne(categoryWrapper);
        if (category == null) {
            throw new CustomException(ResultCodeEnum.CODE_ERROR);
        }
        goods.getParam().put("category", category);
        LambdaQueryWrapper<Business> queryWrapper = Wrappers.lambdaQuery(Business.class).eq(Business::getUuid, goods.getBusinessId());
        Business business = businessService.getOne(queryWrapper);
        goods.getParam().put("business", business);
    }

    /**
     * 保存商品，包括新增和修改
     *
     * @param goods
     */
    @Override
    public void saveGoods(Goods goods, HttpServletRequest request) {
        // 商品标签校验
        fillGoods(goods);
        // 新增
        if (Utils.isEmptyStr(goods.getUuid())) {
            // 先校验code是否已经存在
            QueryWrapper<Goods> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("code", goods.getCode());
            Goods goodsExist = goodsMapper.selectOne(queryWrapper);
            if (goodsExist != null) {
                throw new CustomException(ResultCodeEnum.CODE_EXIST);
            }
            goods.setUuid(UUID.randomUUID().toString().replaceAll("-", ""));
            goods.setCreateTime(new Date());
            goods.setUpdateTime(new Date());
            goods.setPublishDate(new Date());
            goods.setOnLineTime(new Date());
            // 从token获取用户信息，绑定到商户
            Long userId = TokenInfoUtil.getUserId(request);
            Business business = businessService.getByUserId(String.valueOf(userId));
            goods.setBusinessId(business.getUuid());
            goodsMapper.insert(goods);
            //更新
        } else {
            goods.setUpdateTime(new Date());
            // 从token获取用户信息，绑定到商户
            Long userId = TokenInfoUtil.getUserId(request);
            Business business = businessService.getByUserId(String.valueOf(userId));
            goods.setBusinessId(business.getUuid());
            // 根据uuid进行更新
            QueryWrapper<Goods> updateWrapper = new QueryWrapper<>();
            updateWrapper.eq("uuid", goods.getUuid());
            goodsMapper.update(goods, updateWrapper);
        }
    }

    /**
     * 上传商品图片
     *
     * @param file 图片文件
     * @return
     * @throws IOException
     */
    @Override
    public String uploadImg(MultipartFile file) throws IOException {
        // 先判断桶是否存在
        if (!MinioUtil.bucketExists(minioConfig.getBucketName())) {
            // 不存在需要先创建
            MinioUtil.createBucket(minioConfig.getBucketName());
        }
        //文件重命名
        String originalFilename = "temp_file_" + file.getOriginalFilename();
        String[] filename = originalFilename.split("\\.");//拆后缀
        //临时文件
        File tempFile = File.createTempFile(filename[0], "");
        file.transferTo(tempFile);
        //重命名
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        String newName = uuid + file.getOriginalFilename();
        tempFile = FileUtil.rename(tempFile, newName, true, true);
        InputStream inputStream = new FileInputStream(tempFile);
        //File转换成MultipartFile
        file = new MockMultipartFile(tempFile.getName(), tempFile.getName(), filename[filename.length - 1], inputStream);
        //程序退出后删除临时文件
        tempFile.deleteOnExit();
        String url = MinioUtil.upload(minioConfig.getBucketName(), file);
        return url;
    }

    /**
     * 删除商品
     *
     * @param uuid
     */
    @Override
    public void deleteGoods(String uuid) {
        LambdaQueryWrapper<Goods> wrapper = Wrappers.lambdaQuery(Goods.class).eq(Goods::getUuid, uuid);
        goodsMapper.delete(wrapper);
    }

    /**
     * 获取商品详情信息
     *
     * @param uuid
     * @return
     */
    @Override
    public Goods getGoodDetail(String uuid) {
        LambdaQueryWrapper<Goods> queryWrapper = Wrappers.lambdaQuery(Goods.class).eq(Goods::getUuid, uuid);
        Goods goods = goodsMapper.selectOne(queryWrapper);
        fillGoods(goods);
        return goods;
    }

    /**
     * 商品的上线/下线
     *
     * @param uuid   商品的uuid
     * @param onLine 需要变更的状态
     */
    @Override
    public void onLine(String uuid, String onLine) {
        LambdaQueryWrapper<Goods> queryWrapper = Wrappers.lambdaQuery(Goods.class).eq(Goods::getUuid, uuid);
        Goods goods = goodsMapper.selectOne(queryWrapper);
        goods.setOnLine(onLine);
        goods.setUpdateTime(new Date());
        goods.setOnLineTime(new Date());
        goodsMapper.updateById(goods);
    }
}
